package at.fhooe.mcm12.java.application;

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

import javax.swing.DefaultListModel;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.ScrollPaneConstants;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import at.fhooe.mcm12.java.clients.AbstractClient;
import at.fhooe.mcm12.java.clients.ClientManager;
import at.fhooe.mcm12.java.interfaces.RMIClientManager;
import at.fhooe.mcm12.java.interfaces.RMISensorControllerInterface;
import at.fhooe.mcm12.java.interfaces.RMISensorInterface;
import at.fhooe.mcm12.java.sensors.AbstractSensor;

/**
 * 
 * @author Michael Schoellhammer
 * 
 */
public class SensorGUIManager extends JFrame {

	private RMISensorControllerInterface m_sensorController;
	private RMIClientManager m_clientManager;

	private DefaultListModel<AbstractClient> m_clientList;
	private DefaultListModel<RMISensorInterface> m_sensorList;
	private DefaultListModel<String> m_sensorListDisplay;
	private DefaultListModel<RMISensorInterface> m_sensorListForClient;
	private DefaultListModel<String> m_sensorListForClientDisplay;

	private JPanel contentPane;
	private JTextField txtSensorName;
	private JTextField txtSensorType;
	private JTextField txtClientName;
	private JTextArea txtSensorDescription;
	//private JList<RMISensorInterface> lstSubscribableSensors;
	//private JList<RMISensorInterface> lstRegisteredSensors;
	private JList<String> lstSubscribableSensors;
	private JList<String> lstRegisteredSensors;
	private JList<AbstractClient> lstActiveClients;
	private JCheckBox chkActive;

	public SensorGUIManager(String name) {
		this();
		
		initiateRMIClient();

		try {
			m_sensorController = m_clientManager.getSensorController();
		} catch (RemoteException e1) {
			e1.printStackTrace();
		}

		m_clientList = new DefaultListModel<AbstractClient>();
		try {
			for (AbstractClient c : m_clientManager.getClients()) {
				m_clientList.addElement(c);
			}
		} catch (RemoteException e1) {
			e1.printStackTrace();
		}

		m_sensorList = new DefaultListModel<RMISensorInterface>();
		m_sensorListDisplay = new DefaultListModel<String>();
		try {
			for (RMISensorInterface s : m_sensorController.getSubscribableSensors()) {
				m_sensorList.addElement(s);
				m_sensorListDisplay.addElement(s.getName());
			}
		} catch (RemoteException e) {
			e.printStackTrace();
		}

		m_sensorListForClient = new DefaultListModel<RMISensorInterface>();
		m_sensorListForClientDisplay = new DefaultListModel<String>();
		
		lstActiveClients.setModel(m_clientList);
		//lstSubscribableSensors.setModel(m_sensorList);
		//lstRegisteredSensors.setModel(m_sensorListForClient);
		lstSubscribableSensors.setModel(m_sensorListDisplay);
		lstRegisteredSensors.setModel(m_sensorListForClientDisplay);

	}
	
	private void initiateRMIClient() {
		System.setProperty("java.security.policy", "file:./res/rmi.policy");
		if (System.getSecurityManager() == null) {
			System.setSecurityManager(new SecurityManager());
		}

		try {
			Registry remoteRegistry = LocateRegistry.getRegistry(RMIClientManager.HOST, Registry.REGISTRY_PORT);
			m_clientManager = (RMIClientManager) remoteRegistry.lookup(RMIClientManager.NAME);
		} catch (RemoteException | NotBoundException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {

			public void run() {
				try {
					SensorGUIManager frame = new SensorGUIManager("SensorManager");
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the frame.
	 */
	public SensorGUIManager() {
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 652, 432);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		contentPane.setLayout(new BorderLayout(0, 0));
		setContentPane(contentPane);

		JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);		
		contentPane.add(tabbedPane, BorderLayout.CENTER);

		JPanel tabClients = new JPanel();
		tabbedPane.addTab("Clients", null, tabClients, null);
		tabClients.setLayout(new BorderLayout(10, 10));

		JPanel pnlActiveClients = new JPanel();
		tabClients.add(pnlActiveClients, BorderLayout.WEST);
		pnlActiveClients.setLayout(new BorderLayout(0, 0));

		JLabel lblActiveClients = new JLabel("Active clients:");
		pnlActiveClients.add(lblActiveClients, BorderLayout.NORTH);

		JScrollPane scrlActiveClients = new JScrollPane();
		scrlActiveClients
				.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
		scrlActiveClients
				.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
		pnlActiveClients.add(scrlActiveClients, BorderLayout.CENTER);

		lstActiveClients = new JList<AbstractClient>();
		lstActiveClients.addListSelectionListener(new ListSelectionListener() {
			public void valueChanged(ListSelectionEvent evt) {
//				if (!evt.getValueIsAdjusting()) {
					int idx = lstActiveClients.getSelectedIndex();
					AbstractClient client = m_clientList.get(idx);
					txtClientName.setText(client.getName());
					m_sensorListForClient.removeAllElements();
					m_sensorListForClientDisplay.removeAllElements();
					try {
						for (RMISensorInterface sensor : m_clientManager
								.getSensorsForClient(client)) {
							m_sensorListForClient.addElement(sensor);
							m_sensorListForClientDisplay.addElement(sensor.getName());
						}
					} catch (RemoteException e) {
						e.printStackTrace();
					}
					//System.out.println("Selected sensor: " + client
						//	+ ", name: " + client.getName());
//				}
			}
		});
		lstActiveClients.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		scrlActiveClients.setViewportView(lstActiveClients);

		JPanel pnlSelectedClient = new JPanel();
		tabClients.add(pnlSelectedClient, BorderLayout.CENTER);
		GridBagLayout gbl_pnlSelectedClient = new GridBagLayout();
		gbl_pnlSelectedClient.columnWidths = new int[] { 61, 0, 0 };
		gbl_pnlSelectedClient.rowHeights = new int[] { 0, 0, 0, 110, 0 };
		gbl_pnlSelectedClient.columnWeights = new double[] { 0.0, 1.0,
				Double.MIN_VALUE };
		gbl_pnlSelectedClient.rowWeights = new double[] { 0.0, 0.0, 0.0, 0.0,
				Double.MIN_VALUE };
		pnlSelectedClient.setLayout(gbl_pnlSelectedClient);

		JLabel lblSelectedClient = new JLabel("Selected client:");
		GridBagConstraints gbc_lblSelectedClient = new GridBagConstraints();
		gbc_lblSelectedClient.fill = GridBagConstraints.HORIZONTAL;
		gbc_lblSelectedClient.gridwidth = 2;
		gbc_lblSelectedClient.insets = new Insets(0, 0, 5, 0);
		gbc_lblSelectedClient.gridx = 0;
		gbc_lblSelectedClient.gridy = 0;
		pnlSelectedClient.add(lblSelectedClient, gbc_lblSelectedClient);

		JLabel lblClientName = new JLabel("Name:");
		GridBagConstraints gbc_lblClientName = new GridBagConstraints();
		gbc_lblClientName.anchor = GridBagConstraints.EAST;
		gbc_lblClientName.insets = new Insets(0, 0, 5, 5);
		gbc_lblClientName.gridx = 0;
		gbc_lblClientName.gridy = 1;
		pnlSelectedClient.add(lblClientName, gbc_lblClientName);

		txtClientName = new JTextField();
		txtClientName.setEditable(false);
		txtClientName.setColumns(10);
		GridBagConstraints gbc_txtClientName = new GridBagConstraints();
		gbc_txtClientName.insets = new Insets(0, 0, 5, 0);
		gbc_txtClientName.fill = GridBagConstraints.HORIZONTAL;
		gbc_txtClientName.gridx = 1;
		gbc_txtClientName.gridy = 1;
		pnlSelectedClient.add(txtClientName, gbc_txtClientName);

		JLabel lblRegisteredSensors = new JLabel("Registered sensors:");
		GridBagConstraints gbc_lblRegisteredSensors = new GridBagConstraints();
		gbc_lblRegisteredSensors.anchor = GridBagConstraints.EAST;
		gbc_lblRegisteredSensors.insets = new Insets(0, 0, 5, 5);
		gbc_lblRegisteredSensors.gridx = 0;
		gbc_lblRegisteredSensors.gridy = 2;
		pnlSelectedClient.add(lblRegisteredSensors, gbc_lblRegisteredSensors);

		JPanel pnlRegisteredSensors = new JPanel();
		GridBagConstraints gbc_pnlRegisteredSensors = new GridBagConstraints();
		gbc_pnlRegisteredSensors.gridheight = 2;
		gbc_pnlRegisteredSensors.fill = GridBagConstraints.BOTH;
		gbc_pnlRegisteredSensors.gridx = 1;
		gbc_pnlRegisteredSensors.gridy = 2;
		pnlSelectedClient.add(pnlRegisteredSensors, gbc_pnlRegisteredSensors);
		pnlRegisteredSensors.setLayout(new BorderLayout(0, 0));

		JScrollPane scrlRegisteredSensors = new JScrollPane();
		pnlRegisteredSensors.add(scrlRegisteredSensors);

		lstRegisteredSensors = new JList<String>();
		lstRegisteredSensors
				.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		scrlRegisteredSensors.setViewportView(lstRegisteredSensors);

		JPanel tabSensors = new JPanel();
		tabbedPane.addTab("Sensors", null, tabSensors, null);
		tabSensors.setLayout(new BorderLayout(10, 10));

		JPanel pnlActiveSensors = new JPanel();
		tabSensors.add(pnlActiveSensors, BorderLayout.WEST);
		pnlActiveSensors.setLayout(new BorderLayout(0, 0));

		JLabel lblSubscribableSensors = new JLabel("Subscribable sensors:");
		pnlActiveSensors.add(lblSubscribableSensors, BorderLayout.NORTH);

		JScrollPane scrlSubscribableSensors = new JScrollPane();
		scrlSubscribableSensors
				.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
		scrlSubscribableSensors
				.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
		pnlActiveSensors.add(scrlSubscribableSensors, BorderLayout.CENTER);

		lstSubscribableSensors = new JList<String>();
		lstSubscribableSensors
				.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		lstSubscribableSensors
				.addListSelectionListener(new ListSelectionListener() {
					public void valueChanged(ListSelectionEvent evt) {
						if (!evt.getValueIsAdjusting()) {
							int idx = lstSubscribableSensors.getSelectedIndex();
							RMISensorInterface sensor = m_sensorList.get(idx);
							try {
								txtSensorName.setText(sensor.getName());
								txtSensorDescription.setText(sensor
										.getDescription());
								txtSensorType.setText("" + sensor.getSensorType());
								chkActive.setSelected(sensor.isActive());
								chkActive.setEnabled(true);
							} catch (RemoteException e) {
								e.printStackTrace();
							}
						}
					}
				});
		scrlSubscribableSensors.setViewportView(lstSubscribableSensors);

		JPanel pnlSelectedSensor = new JPanel();
		tabSensors.add(pnlSelectedSensor, BorderLayout.CENTER);
		GridBagLayout gbl_pnlSelectedSensor = new GridBagLayout();
		gbl_pnlSelectedSensor.columnWidths = new int[] { 61, 0, 0 };
		gbl_pnlSelectedSensor.rowHeights = new int[] { 0, 0, 0, 0, 0, 0, 0 };
		gbl_pnlSelectedSensor.columnWeights = new double[] { 0.0, 1.0,
				Double.MIN_VALUE };
		gbl_pnlSelectedSensor.rowWeights = new double[] { 0.0, 0.0, 0.0, 0.0,
				0.0, 0.0, Double.MIN_VALUE };
		pnlSelectedSensor.setLayout(gbl_pnlSelectedSensor);

		JLabel lblSelectedSensor = new JLabel("Selected sensor:");
		GridBagConstraints gbc_lblSelectedSensor = new GridBagConstraints();
		gbc_lblSelectedSensor.gridwidth = 2;
		gbc_lblSelectedSensor.fill = GridBagConstraints.HORIZONTAL;
		gbc_lblSelectedSensor.insets = new Insets(0, 0, 5, 0);
		gbc_lblSelectedSensor.gridx = 0;
		gbc_lblSelectedSensor.gridy = 0;
		pnlSelectedSensor.add(lblSelectedSensor, gbc_lblSelectedSensor);

		JLabel lblName = new JLabel("Name:");
		GridBagConstraints gbc_lblName = new GridBagConstraints();
		gbc_lblName.insets = new Insets(0, 0, 5, 5);
		gbc_lblName.anchor = GridBagConstraints.EAST;
		gbc_lblName.gridx = 0;
		gbc_lblName.gridy = 1;
		pnlSelectedSensor.add(lblName, gbc_lblName);

		txtSensorName = new JTextField();
		txtSensorName.setEditable(false);
		GridBagConstraints gbc_txtSensorName = new GridBagConstraints();
		gbc_txtSensorName.insets = new Insets(0, 0, 5, 0);
		gbc_txtSensorName.fill = GridBagConstraints.HORIZONTAL;
		gbc_txtSensorName.gridx = 1;
		gbc_txtSensorName.gridy = 1;
		pnlSelectedSensor.add(txtSensorName, gbc_txtSensorName);
		txtSensorName.setColumns(10);

		JLabel lblDescription = new JLabel("Description:");
		GridBagConstraints gbc_lblDescription = new GridBagConstraints();
		gbc_lblDescription.anchor = GridBagConstraints.EAST;
		gbc_lblDescription.insets = new Insets(0, 0, 5, 5);
		gbc_lblDescription.gridx = 0;
		gbc_lblDescription.gridy = 2;
		pnlSelectedSensor.add(lblDescription, gbc_lblDescription);

		JPanel pnlSensorDescription = new JPanel();
		GridBagConstraints gbc_pnlSensorDescription = new GridBagConstraints();
		gbc_pnlSensorDescription.gridheight = 2;
		gbc_pnlSensorDescription.insets = new Insets(0, 0, 5, 0);
		gbc_pnlSensorDescription.fill = GridBagConstraints.BOTH;
		gbc_pnlSensorDescription.gridx = 1;
		gbc_pnlSensorDescription.gridy = 2;
		pnlSelectedSensor.add(pnlSensorDescription, gbc_pnlSensorDescription);
		pnlSensorDescription.setLayout(new BorderLayout(0, 0));

		JScrollPane scrlSensorDescription = new JScrollPane();
		pnlSensorDescription.add(scrlSensorDescription);
		scrlSensorDescription
				.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
		scrlSensorDescription
				.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);

		txtSensorDescription = new JTextArea();
		txtSensorDescription.setBackground(UIManager
				.getColor("TextField.inactiveBackground"));
		txtSensorDescription.setEditable(false);
		txtSensorDescription.setRows(8);
		scrlSensorDescription.setViewportView(txtSensorDescription);

		JLabel lblSensorType = new JLabel("Sensor type:");
		GridBagConstraints gbc_lblSensorType = new GridBagConstraints();
		gbc_lblSensorType.anchor = GridBagConstraints.EAST;
		gbc_lblSensorType.insets = new Insets(0, 0, 5, 5);
		gbc_lblSensorType.gridx = 0;
		gbc_lblSensorType.gridy = 4;
		pnlSelectedSensor.add(lblSensorType, gbc_lblSensorType);

		txtSensorType = new JTextField();
		txtSensorType.setEditable(false);
		GridBagConstraints gbc_txtSensorType = new GridBagConstraints();
		gbc_txtSensorType.insets = new Insets(0, 0, 5, 0);
		gbc_txtSensorType.fill = GridBagConstraints.HORIZONTAL;
		gbc_txtSensorType.gridx = 1;
		gbc_txtSensorType.gridy = 4;
		pnlSelectedSensor.add(txtSensorType, gbc_txtSensorType);
		txtSensorType.setColumns(10);

		chkActive = new JCheckBox("Active");
		chkActive.addItemListener(new ItemListener() {
			public void itemStateChanged(ItemEvent evt) {
				int idx = lstSubscribableSensors.getSelectedIndex();
				RMISensorInterface sensor = m_sensorList.get(idx);
				try {
					if (chkActive.isSelected()) {
						m_sensorController.enableSensor(sensor);
					} else {
						m_sensorController.disableSensor(sensor);
					}
				} catch (RemoteException e) {
					e.printStackTrace();
				}
			}
		});
		
		chkActive.setEnabled(false);
		GridBagConstraints gbc_chkActive = new GridBagConstraints();
		gbc_chkActive.anchor = GridBagConstraints.WEST;
		gbc_chkActive.gridx = 1;
		gbc_chkActive.gridy = 5;
		pnlSelectedSensor.add(chkActive, gbc_chkActive);
	}
}
